#include "CTableBase.h"
#include "CppSQLite3.h"
#include <sstream>
#include <algorithm>
#include <set>
#include <boost/uuid/uuid.hpp>           
#include <boost/uuid/uuid_generators.hpp> 
#include <boost/uuid/uuid_io.hpp>       
#include <iostream>

// Suppress deprecated API warnings for SQLite3
#ifdef _WIN32
#pragma warning(disable: 4996)
#endif

CTableBase::CTableBase()
	: m_tableConfigure(nullptr),
	  m_logDatabase(nullptr),
	  m_level(10), m_uploadFailedCount(0), m_uploadedCursor(0)
{
}

int CTableBase::getTableType() const
{
	return TableTypeUnknown;
}

std::string CTableBase::getTableName() const
{
	if ( m_tableConfigure )
		return m_tableConfigure->getTableName();

	return ""; // Return empty string if no configuration is set
}

void CTableBase::setTableConfigure(const CTableConfigurePtr& tableConfigure)
{
	m_tableConfigure = tableConfigure;
}
CTableConfigurePtr CTableBase::getTableConfigure() const
{
	return m_tableConfigure;
}

void CTableBase::setLogDatabase(const CLogDatabasePtr& logDatabase)
{
	m_logDatabase = logDatabase;
}

CLogDatabasePtr CTableBase::getLogDatabase() const
{
	return m_logDatabase;
}

const std::map<std::string, CTableField>& CTableBase::getTableFields() const
{
	return m_tableFields;
}

std::vector<CTableField> CTableBase::getTableFieldsBySql()
{
	std::vector<CTableField> tableFields;
	try {
		// Check if we have the required components
		if (!m_tableConfigure || !m_logDatabase) {
			return tableFields; // Error: missing configuration or database
		}
		
		// Get the database connection
		CppSQLite3DB* db = m_logDatabase->getDatabaseConnection();
		if (!db) {
			return tableFields; // Error: no database connection
		}
		
		// Get the table name
		std::string tableName = m_tableConfigure->getTableName();
		if (tableName.empty()) {
			return tableFields; // Error: no table name
		}
		
		// Check if the table exists
		if (!db->tableExists(tableName.c_str())) {
			return tableFields; // Error: table doesn't exist
		}
		
		// Clear existing fields
		m_tableFields.clear();
		
		// SQL query to get table schema information
		std::stringstream sql;
		sql << "PRAGMA table_info(" << tableName << ")";
		
		// Execute the query
		CppSQLite3Query query = db->execQuery(sql.str().c_str());
		
		// Process the results
		while (!query.eof()) {
			// Get field information from the query
			// PRAGMA table_info returns: cid, name, type, notnull, dflt_value, pk
			std::string fieldName = query.getStringField("name");
			std::string fieldType = query.getStringField("type");
			
			// Convert SQLite type to our EFieldType
			EFieldType type = EFieldType::EFieldTypeUnknown;
			int fieldSize = 0;
			
			// Convert to lowercase for comparison
			std::string lowerType = fieldType;
			std::transform(lowerType.begin(), lowerType.end(), lowerType.begin(), ::tolower);
			
			if (lowerType.find("int") != std::string::npos) {
				type = EFieldType::EFieldTypeInt;
			} else if (lowerType.find("real") != std::string::npos || 
					   lowerType.find("float") != std::string::npos || 
					   lowerType.find("double") != std::string::npos) {
				type = EFieldType::EFieldTypeFloat;
			} else if (lowerType.find("text") != std::string::npos || 
					   lowerType.find("char") != std::string::npos || 
					   lowerType.find("varchar") != std::string::npos) {
				type = EFieldType::EFieldTypeString;
				
				// Try to extract size from type (e.g., VARCHAR(255))
				size_t start = fieldType.find('(');
				size_t end = fieldType.find(')');
				if (start != std::string::npos && end != std::string::npos && start < end) {
					std::string sizeStr = fieldType.substr(start + 1, end - start - 1);
					fieldSize = std::stoi(sizeStr);
				}
			}
			
			// Create CTableField and add to the map
			CTableField field(fieldName, type, fieldSize);
			m_tableFields[fieldName] = field;
			tableFields.push_back(field);
			
			// Move to next row
			query.nextRow();
		}
		
		// Finalize the query
		query.finalize();
		
		return tableFields; // Success
		
	} catch (const CppSQLite3Exception& e) {
		// Handle SQLite exceptions
		return tableFields; // Error: SQLite exception
	} catch (const std::exception& e) {
		// Handle other exceptions
		return tableFields; // Error: general exception
	}
}

int CTableBase::createrTableBySql()
{
	try {
		// Check if we have the required components
		if (!m_tableConfigure || !m_logDatabase) {
			return -1; // Error: missing configuration or database
		}
		
		// Get the database connection
		CppSQLite3DB* db = m_logDatabase->getDatabaseConnection();
		if (!db) {
			return -2; // Error: no database connection
		}
		
		// Get the CREATE TABLE SQL statement
		std::string createTableSql = getCreateTableSql();
		if (createTableSql.empty()) {
			return -3; // Error: failed to generate CREATE TABLE SQL
		}
		
		// Execute the CREATE TABLE statement
		db->execDML(createTableSql.c_str());
		
		// Reset the auto-increment sequence to start from 1
		// This ensures that the first inserted record will have ID = 1
		
		return 0; // Success
		
	} catch (const CppSQLite3Exception& e) {
		// Handle SQLite exceptions
		return -4; // Error: SQLite exception
	} catch (const std::exception& e) {
		// Handle other exceptions
		return -5; // Error: general exception
	}
}

int CTableBase::updateTableBySql()
{
	try {
		// Check if we have the required components
		if (!m_tableConfigure || !m_logDatabase) {
			return -1; // Error: missing configuration or database
		}
		
		// Get the database connection
		CppSQLite3DB* db = m_logDatabase->getDatabaseConnection();
		if (!db) {
			return -2; // Error: no database connection
		}
		
		// Get the UPDATE TABLE SQL statement
		std::string updateTableSql = getUpdateTableSql();
		if (updateTableSql.empty()) {
			return 0; // No update needed
		}
		
		// Execute the UPDATE TABLE statements
		db->execDML(updateTableSql.c_str());
		
		return 0; // Success
		
	} catch (const CppSQLite3Exception& e) {
		// Handle SQLite exceptions
		return -3; // Error: SQLite exception
	} catch (const std::exception& e) {
		// Handle other exceptions
		return -4; // Error: general exception
	}
}

int CTableBase::initUploadCursor()
{
	try {
		// Check if we have the required components
		if (!m_tableConfigure || !m_logDatabase) {
			return -1; // Error: missing configuration or database
		}
		
		// Get the table name
		std::string tableName = m_tableConfigure->getTableName();
		if (tableName.empty()) {
			return -2; // Error: no table name
		}
		
		// Get the database connection
		CppSQLite3DB* db = m_logDatabase->getDatabaseConnection();
		if (!db) {
			return -3; // Error: no database connection
		}
		
		// Try to get existing cursor information from nonius table
		uint64_t startTime, lastTime;
		int tableId;
		int result = m_logDatabase->getNoniusCursor(tableName, startTime, lastTime, tableId);
		
		if (result == 0) {
			// Cursor exists, set the uploaded cursor to the last time
			m_uploadedCursor = lastTime;
			std::cout << "Initialized upload cursor for table " << tableName 
					  << " to time: " << m_uploadedCursor << std::endl;
			return 0; // Success
		} else if (result == -4) {
			// No cursor found, initialize to 0 (no records uploaded yet)
			m_uploadedCursor = 0;
			std::cout << "No upload cursor found for table " << tableName 
					  << ", initialized to 0" << std::endl;
			return 0; // Success
		} else {
			// Other error occurred
			std::cerr << "Error getting nonius cursor for table " << tableName 
					  << ", error code: " << result << std::endl;
			return result;
		}
		
	} catch (const std::exception& e) {
		// Handle exceptions
		std::cerr << "Exception in initUploadCursor: " << e.what() << std::endl;
		return -5; // Error: general exception
	}
}

std::string CTableBase::getCreateTableSql()
{
	try {
		// Check if we have the required components
		if (!m_tableConfigure) {
			return ""; // Error: missing configuration
		}
		
		// Get the table name
		std::string tableName = m_tableConfigure->getTableName();
		if (tableName.empty()) {
			return ""; // Error: no table name
		}
		
		// Get the field configurations
		auto& configFieldMap = m_tableConfigure->getTableFieldTypeMap();
		if (configFieldMap.empty()) {
			return ""; // Error: no field configurations
		}
		
		// Build CREATE TABLE statement
		std::stringstream sql;
		sql << "CREATE TABLE IF NOT EXISTS " << tableName << " (";
		
		// Add id field first (auto-increment primary key)
		sql << "id INTEGER PRIMARY KEY AUTOINCREMENT";
		
		// Add other fields
		for (const auto& fieldPair : configFieldMap) {
			const CTableField& field = fieldPair.second;
			std::string fieldName = field.getFieldName();
			
			// Skip id field as it's already added
			if (fieldName == "id") {
				continue;
			}
			
			sql << ", " << fieldName << " ";
			
			// Add field type based on EFieldType
			switch (field.getFieldType()) {
				case EFieldType::EFieldTypeInt:
					sql << "INTEGER";
					break;
				case EFieldType::EFieldTypeFloat:
					sql << "REAL";
					break;
				case EFieldType::EFieldTypeString:
					if (field.getFieldSize() > 0) {
						sql << "VARCHAR(" << field.getFieldSize() << ")";
					} else {
						sql << "TEXT";
					}
					break;
				default:
					sql << "TEXT"; // Default to TEXT for unknown types
					break;
			}
		}
		
		sql << ")";
		
		return sql.str();
		
	} catch (const std::exception& e) {
		// Handle exceptions
		return ""; // Error: general exception
	}
}

std::string CTableBase::getUpdateTableSql()
{
	try {
		// Check if we have the required components
		if (!m_tableConfigure) {
			return ""; // Error: missing configuration
		}
		
		// Get the table name
		std::string tableName = m_tableConfigure->getTableName();
		if (tableName.empty()) {
			return ""; // Error: no table name
		}
		
		// Get the field configurations
		auto& configFieldMap = m_tableConfigure->getTableFieldTypeMap();
		if (configFieldMap.empty()) {
			return ""; // Error: no field configurations
		}
		
		// Get existing table fields
		auto existingFields = getTableFieldsBySql();
		if (existingFields.empty()) {
			return ""; // Error: failed to get existing fields
		}
		
		// Create a set of existing field names for quick lookup
		std::set<std::string> existingFieldNames;
		for (const auto& field : existingFields) {
			existingFieldNames.insert(field.getFieldName());
		}
		
		// Find missing fields (fields in configuration but not in existing table)
		std::vector<std::string> missingFields;
		for (const auto& fieldPair : configFieldMap) {
			std::string fieldName = fieldPair.first;
			if (existingFieldNames.find(fieldName) == existingFieldNames.end()) {
				missingFields.push_back(fieldName);
			}
		}
		
		// If no missing fields, return empty string
		if (missingFields.empty()) {
			return "";
		}
		
		// Generate ALTER TABLE statements for missing fields
		std::stringstream sql;
		bool firstStatement = true;
		
		for (const auto& fieldName : missingFields) {
			// Find the field configuration
			auto it = configFieldMap.find(fieldName);
			if (it == configFieldMap.end()) {
				continue; // Skip if field not found in configuration
			}
			
			const CTableField& field = it->second;
			
			// Add separator between statements
			if (!firstStatement) {
				sql << "; ";
			}
			firstStatement = false;
			
			// Generate ALTER TABLE ADD COLUMN statement
			sql << "ALTER TABLE " << tableName << " ADD COLUMN " << fieldName << " ";
			
			// Add field type based on EFieldType
			switch (field.getFieldType()) {
				case EFieldType::EFieldTypeInt:
					sql << "INTEGER";
					break;
				case EFieldType::EFieldTypeFloat:
					sql << "REAL";
					break;
				case EFieldType::EFieldTypeString:
					if (field.getFieldSize() > 0) {
						sql << "VARCHAR(" << field.getFieldSize() << ")";
					} else {
						sql << "TEXT";
					}
					break;
				default:
					sql << "TEXT"; // Default to TEXT for unknown types
					break;
			}
		}
		
		return sql.str();
		
	} catch (const std::exception& e) {
		// Handle exceptions
		return ""; // Error: general exception
	}
}

std::string CTableBase::generateUUID()
{
	boost::uuids::random_generator generator;
	boost::uuids::uuid uuid = generator();
	return boost::uuids::to_string(uuid);
}

uint64_t CTableBase::getTimestamp()
{
	time_t now = time(NULL);
	now *= 1000; // Convert to milliseconds
	return (uint64_t)now;
}

// Helper method to calculate the approximate size of a log record in bytes
uint64_t CTableBase::calculateRecordSize(CLogRecordPtr logRecord)
{
	uint64_t totalSize = 0;
	
	if (!logRecord) {
		return totalSize;
	}
	
	// Add overhead for record structure (field names, separators, etc.)
	totalSize += 100; // Base overhead
	
	// Calculate size of each field
	auto& fields = logRecord->GetFields();
	for (const auto& fieldPair : fields) {
		const std::string& fieldName = fieldPair.first;
		const CLogFieldPtr& field = fieldPair.second;
		
		// Add field name size
		totalSize += fieldName.length();
		
		// Add field value size based on type
		const CLogValue& value = field->GetValue();
		if (value.type() == typeid(uint64_t)) {
			totalSize += sizeof(uint64_t);
		} else if (value.type() == typeid(double)) {
			totalSize += sizeof(double);
		} else if (value.type() == typeid(std::string)) {
			totalSize += boost::get<std::string>(value).length();
		}
		
		// Add overhead for field structure (separators, quotes, etc.)
		totalSize += 20; // Field overhead
	}
	
	return totalSize;
}

int CTableBase::InitTable()
{
	m_tableConfigure->setTableField(CTableField("auth_id", EFieldType::EFieldTypeInt, 0));
	m_tableConfigure->setTableField(CTableField("stm", EFieldType::EFieldTypeInt, 0));
	m_tableConfigure->setTableField(CTableField("ltm", EFieldType::EFieldTypeInt, 0));
	m_tableConfigure->setTableField(CTableField("op", EFieldType::EFieldTypeInt, 0));
	m_tableConfigure->setTableField(CTableField("uuid", EFieldType::EFieldTypeString, 36));


	try {
		
		// Create the table in the database
		int result = createrTableBySql();
		if (result != 0) {
			return result; // Return error code from table creation
		}
		
		// Get the table fields from the database
		auto tableFields = getTableFieldsBySql();
		if (tableFields.empty()) {
			return result; // Return error code from field retrieval
		}
		
		// Update table if needed (add missing columns)
		result = updateTableBySql();
		if (result != 0) {
			return result; // Return error code from table update
		}
		
		//重新获取表字段
		tableFields = getTableFieldsBySql();

		return initUploadCursor(); // Success
		
	} catch (const std::exception& e) {
		return -1; // Error: general exception
	}
}

int CTableBase::getLevel()
{
	return m_level;
}

uint64_t CTableBase::getUploadedCursor()
{
	return m_uploadedCursor;
}

int CTableBase::updateUploadCursor(uint64_t newCursor)
{
	try {
		// Check if we have the required components
		if (!m_tableConfigure || !m_logDatabase) {
			return -1; // Error: missing configuration or database
		}
		
		// Get the table name
		std::string tableName = m_tableConfigure->getTableName();
		if (tableName.empty()) {
			return -2; // Error: no table name
		}
		
		// Update the local cursor
		m_uploadedCursor = newCursor;
		
		// Get table ID (you might need to add this to CTableConfigure or derive it somehow)
		// For now, we'll use a default value
		int tableId = 0; // Default table ID
		
		// Update the nonius cursor in database
		int result = m_logDatabase->updateNoniusCursor(tableName, tableId, newCursor);
		if (result != 0) {
			std::cerr << "Failed to update nonius cursor for table: " << tableName << std::endl;
			return result;
		}
		
		std::cout << "Successfully updated upload cursor for table " << tableName 
				  << " to: " << newCursor << std::endl;
		
		return 0; // Success
		
	} catch (const std::exception& e) {
		// Handle exceptions
		std::cerr << "Exception in updateUploadCursor: " << e.what() << std::endl;
		return -5; // Error: general exception
	}
}

int CTableBase::writeLog(CLogBatchPtr logBatch)
{
	m_logDatabase->lock();

	logBatch->enumLogRecord([=](CLogRecordPtr record) -> int
		{
			return writeRecord(record);
		});

	m_logDatabase->unlock();

	return 0;
}

int CTableBase::writeRecord(CLogRecordPtr logRecord)
{
	return 0;
}

int CTableBase::beforeWriteLog(CLogBatchPtr logBatch)
{
	logBatch->enumLogRecord([=](CLogRecordPtr record) -> int
		{
			return beforeWriteRecord(record);
		});

	return 0;
}

int CTableBase::beforeWriteRecord(CLogRecordPtr logRecord)
{
	if (!logRecord->hasField("op"))
		logRecord->AddField("op", (uint64_t)0);

	uint64_t now = getTimestamp();
	
	if (!logRecord->hasField("stm"))
		logRecord->AddField("stm", now);
	
	if (!logRecord->hasField("ltm"))
		logRecord->AddField("ltm", now);
	
	if (!logRecord->hasField("auth_id"))
		logRecord->AddField("auth_id", "");

	if (!logRecord->hasField("uuid"))
		logRecord->AddField("uuid", generateUUID());

	return 0;
}

int CTableBase::getUploadBatch(CUpLoadBatchPtr uploadBatch)
{
	try {
		// Check if we have the required components
		if (!m_tableConfigure || !m_logDatabase || !uploadBatch) {
			return -1; // Error: missing configuration, database, or upload batch
		}
		
		boost::lock_guard<CLogDatabase> lock(*m_logDatabase);

		// Get the database connection
		CppSQLite3DB* db = m_logDatabase->getDatabaseConnection();
		if (!db) {
			return -2; // Error: no database connection
		}
		
		// Get the table name
		std::string tableName = m_tableConfigure->getTableName();
		if (tableName.empty()) {
			return -3; // Error: no table name
		}
		
		// Set the table name in upload batch
		uploadBatch->SetTableName(tableName);
		
		// Determine the number of records to retrieve based on table type
		int tableType = getTableType();
		int limit = -1; // -1 means no limit (get all records)
		bool isIncrementalTable = false;
		
		// For append-type tables, use configured batch size and apply size limit
		if (tableType == TableTypeAppend || 
			tableType == TableTypeUpAppend || 
			tableType == TableTypeAppendWithCounter) {
			limit = m_tableConfigure->getUpLoadRecordCount();
			isIncrementalTable = true;
		}
		// For update and overlay tables, get all records (no size limit)
		else if (tableType == TableUpdate || tableType == TableTypeOver) {
			limit = -1; // No limit
			isIncrementalTable = false;
		}
		
		// Get max batch size for incremental tables
		uint64_t maxBatchSize = 0;
		if (isIncrementalTable) {
			maxBatchSize = m_tableConfigure->getMaxBanchSize();
		}
		
		// Build SELECT statement - only get records with ID greater than current upload cursor
		std::stringstream sql;
		sql << "SELECT * FROM " << tableName << " WHERE id > " << m_uploadedCursor;
		
		if (limit > 0) {
			sql << " LIMIT " << limit;
		}
		
		// Execute the query
		CppSQLite3Query query = db->execQuery(sql.str().c_str());
		
		uint64_t maxCursor = 0;
		int recordCount = 0;
		uint64_t currentBatchSize = 0;
		std::vector<CLogRecordPtr> tempRecords; // Temporary storage for records
		
		// Process query results
		while (!query.eof()) {
			// Create a new log record
			auto logRecord = std::make_shared<CLogRecord>();
			
			// Get the id field for cursor tracking
			int recordId = query.getIntField("id");
			if (recordId > 0) {
				maxCursor = static_cast<uint64_t>(recordId);
			}
			
			// Add all fields from the query result
			for (int i = 0; i < query.numFields(); i++) {
				std::string fieldName = query.fieldName(i);
				std::string fieldValue = query.getStringField(i);
				
				// Try to convert to appropriate type
				if (fieldName == "id") {
					// Skip id field as it's handled separately
					continue;
				}
				
				// Find the field type from m_tableFields map
				EFieldType fieldType = EFieldType::EFieldTypeString; // Default to string
				auto fieldIt = m_tableFields.find(fieldName);
				if (fieldIt != m_tableFields.end()) {
					fieldType = fieldIt->second.getFieldType();
				}
				
				// Convert value based on field type
				switch (fieldType) {
					case EFieldType::EFieldTypeInt:
						try {
							uint64_t intValue = std::stoull(fieldValue);
							logRecord->AddField(fieldName, intValue);
						} catch (...) {
							// If conversion fails, treat as string
							logRecord->AddField(fieldName, fieldValue);
						}
						break;
						
					case EFieldType::EFieldTypeFloat:
						try {
							double floatValue = std::stod(fieldValue);
							logRecord->AddField(fieldName, floatValue);
						} catch (...) {
							// If conversion fails, treat as string
							logRecord->AddField(fieldName, fieldValue);
						}
						break;
						
					case EFieldType::EFieldTypeString:
					default:
						// Treat as string
						logRecord->AddField(fieldName, fieldValue);
						break;
				}
			}
			
			// Calculate record size
			uint64_t recordSize = calculateRecordSize(logRecord);
			
			// For incremental tables, check if adding this record would exceed max batch size
			if (isIncrementalTable && maxBatchSize > 0) {
				if (currentBatchSize + recordSize > maxBatchSize) {
					// Stop adding records if we would exceed the max batch size
					break;
				}
			}
			
			// Add the record to temporary storage
			tempRecords.push_back(logRecord);
			currentBatchSize += recordSize;
			recordCount++;
			
			// Move to next row
			query.nextRow();
		}
		
		// Finalize the query
		query.finalize();
		
		// Add all collected records to upload batch
		for (const auto& record : tempRecords) {
			uploadBatch->AddRecord(record);
		}
		
		// Set the max cursor
		uploadBatch->SetMaxCursor(maxCursor);
		
		std::cout << "Retrieved " << recordCount << " incremental records for upload from table: " << tableName 
				  << " (ID > " << m_uploadedCursor << ", max cursor: " << maxCursor << ", batch size: " << currentBatchSize << " bytes)" << std::endl;
		
		return 0; // Success
		
	} catch (const CppSQLite3Exception& e) {
		// Handle SQLite exceptions
		//std::cout << "SQLite error in getUploadBatch: " << e.errorMessage() << std::endl;
		return -4; // Error: SQLite exception
	} catch (const std::exception& e) {
		// Handle other exceptions
		//std::cout << "General error in getUploadBatch: " << e.what() << std::endl;
		return -5; // Error: general exception
	}
}

int CTableBase::batchUploadSuccess(CUpLoadBatchPtr uploadBatch)
{
	return updateUploadCursor(uploadBatch->GetMaxCursor());
}

int CTableBase::getUploadFailedCount()
{
	return m_uploadFailedCount;
}

void CTableBase::setUploadFailedCount(int nFailedCount)
{
	m_uploadFailedCount = nFailedCount;
	if (m_uploadFailedCount > m_tableConfigure->getMaxFailedCount())
		m_uploadFailedCount = 0;
}

bool CTableBase::canUpload()
{
	return m_uploadFailedCount < m_tableConfigure->getMaxFailedCount();
}

int CTableBase::InsertRecord(CLogRecordPtr logRecord)
{
	try {
		// Check if we have the required components
		if (!logRecord || !m_tableConfigure || !m_logDatabase) {
			return -1; // Error: missing record, configuration, or database
		}
		
		// Get the database connection
		CppSQLite3DB* db = m_logDatabase->getDatabaseConnection();
		if (!db) {
			return -2; // Error: no database connection
		}
		
		// Get the table name
		std::string tableName = m_tableConfigure->getTableName();
		if (tableName.empty()) {
			return -3; // Error: no table name
		}
		
		// Build INSERT statement
		std::stringstream sql;
		sql << "INSERT INTO " << tableName << " (";
		
		// Add field names (skip id as it's auto-increment)
		bool firstField = true;
		for (const auto& fieldPair : m_tableFields) {
			std::string fieldName = fieldPair.first;
			if (fieldName == "id") {
				continue; // Skip id field as it's auto-increment
			}
			
			if (!firstField) {
				sql << ", ";
			}
			firstField = false;
			sql << fieldName;
		}
		
		sql << ") VALUES (";
		
		// Add placeholders (skip id as it's auto-increment)
		firstField = true;
		for (const auto& fieldPair : m_tableFields) {
			std::string fieldName = fieldPair.first;
			if (fieldName == "id") {
				continue; // Skip id field as it's auto-increment
			}
			
			if (!firstField) {
				sql << ", ";
			}
			firstField = false;
			sql << "?";
		}
		
		sql << ")";
		
		// Prepare the statement
		CppSQLite3Statement stmt = db->compileStatement(sql.str().c_str());
		
		// Bind values
		int paramIndex = 1;
		for (const auto& fieldPair : m_tableFields) {
			std::string fieldName = fieldPair.first;
			if (fieldName == "id") {
				continue; // Skip id field as it's auto-increment
			}
			
			// Get the field value from record
			auto& recordFields = logRecord->GetFields();
			auto it = recordFields.find(fieldName);
			if (it != recordFields.end()) {
				CLogFieldPtr field = it->second;
				const CLogValue& value = field->GetValue();
				
				// Bind value based on type
				if (value.type() == typeid(uint64_t)) {
					stmt.bind(paramIndex, static_cast<sqlite3_int64>(boost::get<uint64_t>(value)));
				} else if (value.type() == typeid(double)) {
					stmt.bind(paramIndex, boost::get<double>(value));
				} else if (value.type() == typeid(std::string)) {
					stmt.bind(paramIndex, boost::get<std::string>(value).c_str());
				} else {
					// Unknown type, bind as NULL
					stmt.bindNull(paramIndex);
				}
			} else {
				// Field not found in record, bind as NULL
				stmt.bindNull(paramIndex);
			}
			
			paramIndex++;
		}
		
		// Execute the statement
		stmt.execDML();
		
		return 0; // Success
		
	} catch (const CppSQLite3Exception& e) {
		// Handle SQLite exceptions
		return -4; // Error: SQLite exception
	} catch (const std::exception& e) {
		// Handle other exceptions
		return -5; // Error: general exception
	}
}
